﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PointAsLine
{
    /// <summary>
    /// 多个polygon是否可以合并
    /// </summary>
    public class SegmentMerger
    {
        /// <summary>
        /// 合并相邻的线段，要求收尾相连的情况
        /// </summary>
        /// <param name="segments"></param>
        /// <param name="threshold"></param>
        /// <returns></returns>
        public static List<Polyline> MergeSegments(List<Polyline> segments, float threshold)
        {
            if (segments == null || segments.Count <= 1)
                return segments;

            // 创建一个副本以避免修改原始列表
            List<Polyline> result = new List<Polyline>(segments);
            bool merged;

            do
            {
                merged = false;
                for (int i = 0; i < result.Count; i++)
                {
                    for (int j = i + 1; j < result.Count; j++)
                    {
                        // 检查两个线段是否可以合并
                        if (AreSegmentsAdjacent(result[i], result[j], threshold))
                        {
                            // 合并线段
                            Polyline mergedSegment = MergeTwoSegments(result[i], result[j]);
                            result.RemoveAt(j);
                            result.RemoveAt(i);
                            result.Insert(i, mergedSegment);
                            merged = true;
                            break; // 退出内层循环，因为列表已修改
                        }
                    }
                    if (merged) break; // 退出外层循环，重新开始合并检查
                }
            } while (merged); // 如果本轮有合并，继续检查

            return result;
        }

        // 检查两个线段是否首尾相邻（在阈值范围内）
        private static bool AreSegmentsAdjacent(Polyline seg1, Polyline seg2, float threshold)
        {
            if (seg1.Count == 0 || seg2.Count == 0)
                return false;

            // 获取两个线段的起点和终点
            PointF2G seg1First = seg1[0];
            PointF2G seg1Last = seg1[seg1.Count - 1];
            PointF2G seg2First = seg2[0];
            PointF2G seg2Last = seg2[seg2.Count - 1];

            // 检查四种可能的连接情况：
            // 1. seg1的尾 -> seg2的头
            // 2. seg1的头 -> seg2的尾
            // 3. seg1的尾 -> seg2的尾
            // 4. seg1的头 -> seg2的头
            var t1 = PointFFunc.Distance(seg1Last, seg2First);
            var t2 = PointFFunc.Distance(seg1First, seg2Last);
            var t3 = PointFFunc.Distance(seg1Last, seg2Last);
            var t4 = PointFFunc.Distance(seg1First, seg2First);
            return t1 <= threshold ||
                    t2 <= threshold ||
                    t3 <= threshold ||
                    t4 <= threshold;
        }

        // 合并两个相邻的线段
        private static Polyline MergeTwoSegments(Polyline seg1, Polyline seg2)
        {
            if (seg1.Count == 0) return seg2;
            if (seg2.Count == 0) return seg1;

            PointF2G seg1First = seg1[0];
            PointF2G seg1Last = seg1[seg1.Count - 1];
            PointF2G seg2First = seg2[0];
            PointF2G seg2Last = seg2[seg2.Count - 1];

            var t1 = PointFFunc.Distance(seg1Last, seg2First);
            var t2 = PointFFunc.Distance(seg1First, seg2Last);
            var t3 = PointFFunc.Distance(seg1Last, seg2Last);
            var t4 = PointFFunc.Distance(seg1First, seg2First);
            if (t1 < t2 && t1 < t3 && t1 < t4)
            {
                Polyline merged = new Polyline(seg1) ;
                for (var i = 0; i < seg2.Count; i++)
                {
                    merged.Add(seg2[i]);
                }
                return merged;
            }
            else if (t2 < t1 && t2 < t3 && t2 < t4)
            {
                Polyline merged = new Polyline(seg2);
                for (var i = 0;i<seg1.Count;i++)
                {
                    merged.Add(seg1[i]);
                }
                return merged;
            }
            else if (t3 < t1 && t3 < t2 && t3 < t4)
            {
                Polyline merged = new Polyline(seg1);
                for (var i = seg2.Count-1;i>=0;i--)
                {
                    merged.Add(seg2[i]);
                }
                return merged;
            }
            else if (t4 < t1 && t4 < t2 && t4 < t3)
            {
                Polyline merged = new Polyline(seg1);
                for(var i = 0; i < seg2.Count; i++)
                {
                    merged.Insert(0, seg2[i]);
                }
                return merged;
            }

            // 确定合并顺序（保持点的顺序）
            if (PointFFunc.Distance(seg1Last, seg2First) <= PointFFunc.Distance(seg1First, seg2Last))
            {
                // seg1 -> seg2 顺序
                Polyline merged = new Polyline(seg1);
                merged.AddRange(seg2);
                return merged;
            }
            else
            {
                // seg2 -> seg1 顺序
                Polyline merged = new Polyline(seg2);
                merged.AddRange(seg1);
                return merged;
            }
        }

       
    }
}
